/*
 * PhotonRTOS础光实时操作系统 -- M核启动文件
 *
 * Copyright (C) 2022, 2023 国科础石(重庆)软件有限公司
 *
 * 作者: Xueming Dong <dongxueming@kernelsoft.com>
 *
 * License terms: GNU General Public License (GPL) version 3
 *
 */

#include <photon/init.h>
#include <photon/types.h>

#include <asm/processor.h>

#include <asm/asm-offsets.h>
#include <asm/process.h>

#include <asm/irq.h>
#include <asm/irqflags.h>
#include <asm/internel.h>
#include <generated/asm-offsets.h>

void __attribute__((weak)) EthernetISR(void);
__attribute__((naked)) void exit(__attribute__((unused)) int status);

extern unsigned int _estack, _sidata, _sdata, _edata, __bss_start, __bss_stop;
extern void vPortSVCHandler(void);
extern void xPortPendSVHandler(void);
extern void xPortSysTickHandler(void);

extern  union process_union master_idle_stack;
void _start(void);
void Reset_Handler(void);

unsigned int g_stack_szie = THREAD_START_SP;

__attribute__((optimize("O0")))
__attribute__((naked))

void Reset_Handler(void)
{
	/**
	 * 设置栈指针
	 */
	asm volatile ("ldr r0, =master_idle_stack");
	asm volatile ("ldr r1, =g_stack_szie");
	asm volatile ("ldr r2, [r1]");
	asm volatile ("add r0, r0, r2");
	asm volatile ("mov sp, r0");

	/**
	 * .bss段清零
	 */
	for (unsigned int *dest = &__bss_start; dest < &__bss_stop;)
		*dest++ = 0;

	_start();
}

void prvGetRegistersFromStack(unsigned int *pulFaultStackAddress);
void prvGetRegistersFromStack(unsigned int *pulFaultStackAddress)
{
	volatile unsigned int r0;
	volatile unsigned int r1;
	volatile unsigned int r2;
	volatile unsigned int r3;
	volatile unsigned int r12;
	volatile unsigned int lr;
	volatile unsigned int pc;
	volatile unsigned int psr;

	r0 = pulFaultStackAddress[0];
	r1 = pulFaultStackAddress[1];
	r2 = pulFaultStackAddress[2];
	r3 = pulFaultStackAddress[3];

	r12 = pulFaultStackAddress[4];
	lr = pulFaultStackAddress[5];
	pc = pulFaultStackAddress[6];
	psr = pulFaultStackAddress[7];

	while (1)
		;

	(void) r0;
	(void) r1;
	(void) r2;
	(void) r3;
	(void) r12;
	(void) lr;
	(void) pc;
	(void) psr;
}

static void Default_Handler(void) __attribute__((naked));
static void Default_Handler(void)
{
	asm volatile
	(
		"Default_Handler:\n"
		"    ldr r3, NVIC_INT_CTRL_CONST\n"
		"    ldr r2, [r3, #0]\n"
		"    uxtb r2, r2\n"
		"Infinite_Loop:\n"
		"    b  Infinite_Loop\n"
		".size  Default_Handler, .-Default_Handler\n"
		".align 4\n"
		"NVIC_INT_CTRL_CONST: .word 0xe000ed04\n"
	);
}
static void Default_Handler2(void) __attribute__((naked));
static void Default_Handler2(void)
{
	asm volatile
	(
		" tst lr, #4\n"
		" ite eq\n"
		" mrseq r0, msp\n"
		" mrsne r0, psp\n"
		" ldr r1, [r0, #24]\n"
		" ldr r2, handler2_address_const\n"
		" bx r2\n"
		" handler2_address_const: .word prvGetRegistersFromStack\n"
	);
}

static void Default_Handler3(void)
{
	while (1)
		;
}

static void Default_Handler4(void)
{
	while (1)
		;
}

static void Default_Handler5(void)
{
	while (1)
		;
}

static void Default_Handler6(void)
{
	while (1)
		;
}

/**
 * 中断向量表
 */
const unsigned int *isr_vector[] __attribute__((section(".isr_vector"))) = {
	(unsigned int *) &_estack,
	(unsigned int *) &Reset_Handler,      /* Reset                -15 */
	(unsigned int *) &Default_Handler,    /* NMI_Handler          -14 */
	(unsigned int *) &Default_Handler2,   /* HardFault_Handler    -13 */
	(unsigned int *) &Default_Handler3,   /* MemManage_Handler    -12 */
	(unsigned int *) &Default_Handler4,   /* BusFault_Handler     -11 */
	(unsigned int *) &Default_Handler5,   /* UsageFault_Handler   -10 */
	0,                                      /* reserved */
	0,                                      /* reserved */
	0,                                      /* reserved */
	0,                                      /* reserved   -6 */
	(unsigned int *) &vPortSVCHandler,    /* SVC_Handler              -5 */
	(unsigned int *) &Default_Handler6,   /* DebugMon_Handler         -4 */
	0,                                      /* reserved */
	(unsigned int *) &xPortPendSVHandler, /* PendSV handler    -2 */
	(unsigned int *) &xPortSysTickHandler,/* SysTick_Handler   -1 */
	0,                                      /* uart0 receive 0 */
	0,                                      /* uart0 transmit */
	0,                                      /* uart1 receive */
	0,                                      /* uart1 transmit */
	0,                                      /* uart 2 receive */
	0,                                      /* uart 2 transmit */
	0,                                      /* GPIO 0 combined interrupt */
	0,                                      /* GPIO 2 combined interrupt */
	0,                                      /* Timer 0 */
	0,                                      /* Timer 1 */
	0,                                      /* Dial Timer */
	0,                                      /* SPI0 SPI1 */
	0,                                      /* uart overflow 1, 2,3 */
	0,                                      /* Ethernet   13 */
};

void _start(void)
{
	start_master();
}

__attribute__((naked)) void exit(__attribute__((unused)) int status)
{
	asm volatile (
		"mov r1, r0\n"
		"cmp r1, #0\n"
		"bne .notclean\n"
		"ldr r1, =0x20026\n"
		".notclean:\n"
		"movs r0, #0x18\n"
		"bkpt 0xab\n"
		"end: b end\n"
	);
}
